package org.example.what_mall.service.impl;

import cn.hutool.crypto.SmUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.example.what_mall.config.JWTConfig;
import org.example.what_mall.dto.UserLoginForm;
import org.example.what_mall.dto.UserSignupForm;
import org.example.what_mall.entity.User;
import org.example.what_mall.enums.UserRole;
import org.example.what_mall.exception.GlobalException;
import org.example.what_mall.mapper.UserMapper;
import org.example.what_mall.service.IUserService;
import org.example.what_mall.util.BloomFilter;
import org.example.what_mall.util.RandomImg;
import org.example.what_mall.util.RedisConstant;
import org.example.what_mall.util.RegexUtil;
import org.example.what_mall.vo.UserDataVO;
import org.example.what_mall.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private JWTConfig jwtConfig;
    @Autowired
    private BloomFilter bloomFilter;

    @Override
    public UserVO login(UserLoginForm form) {

//        System.out.println(form+"*************************");
        String email = form.getAccount();
        if(email == null || email.isEmpty() || !RegexUtil.isEmail(email)) throw new GlobalException(400, "参数验证失败");

        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
        .eq(User::getEmail, email));

        if(user == null) throw new GlobalException(400, "参数验证失败");
        String pwd = form.getPwd();
        if(pwd == null) throw new GlobalException(401, "用户名或密码错误");
        String cPwd = SmUtil.sm3(form.getPwd());
        if(!cPwd.equals(user.getPwd())) throw new GlobalException(401, "用户名或密码错误");

        String token = generateToken(user);
        UserVO userVO = new UserVO();
        userVO.setId(user.getId());
        userVO.setName(user.getNickname());
        userVO.setToken(token);
        return userVO;

    }

    @Transactional
    @Override
    public UserVO signup(UserSignupForm form) {

        if(form.getEmail() == null || form.getEmail().isEmpty() || !RegexUtil.isEmail(form.getEmail())) throw new GlobalException(400, "邮箱已被注册/参数不完整");

//        User isExit = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getEmail, form.getEmail()));
//        if(isExit != null) throw new GlobalException(400, "邮箱已被注册/参数不完整");
        if(bloomFilter.contains(form.getEmail())) {
            User isExit = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getEmail, form.getEmail()));
            if(isExit != null) throw new GlobalException(400, "邮箱已被注册/参数不完整");
        }

        if(form.getPhone()!= null && !RegexUtil.isPhone(form.getPhone())) throw new GlobalException(400, "邮箱已被注册/参数不完整");

        User user = User.builder()
                .email(form.getEmail())
                .nickname(form.getNickname())
                .pwd(SmUtil.sm3(form.getPwd()))
                .recipient(form.getRecipient())
                .address(form.getAddress())
                .phone(form.getPhone())
                .role(UserRole.NORMAL_USER.getCode())
                .headimg(RandomImg.getImgUrl())
                .build();
        userMapper.insert(user);

        bloomFilter.add(form.getEmail());

        String token = generateToken(user);
        UserVO userVO = new UserVO();
        userVO.setId(user.getId());
        userVO.setName(user.getNickname());
        userVO.setToken(token);

        return userVO;
    }

    @Override
    public UserDataVO userData(String token) {
        String keyword = RedisConstant.USER_TOKE_PREFIX + token;
        Map<Object, Object> entity = stringRedisTemplate.opsForHash().entries(keyword);
        Integer userId = Integer.parseInt(entity.get("id").toString());

        User user = userMapper.selectById(userId);
        return UserDataVO.of(user);
    }

    @Override
    public void updateUserData(User vo) {
        userMapper.updateById(vo);
    }

    private String generateToken(User user) {
        String token = jwtConfig.encode(Map.of("id", user.getId(), "name", user.getNickname(), "role", user.getRole()));
        Map<String, String> map = Map.of("token", token, "id", user.getId().toString(), "name", user.getNickname());
        stringRedisTemplate.opsForHash().putAll(RedisConstant.USER_TOKE_PREFIX +token, map);
        stringRedisTemplate.expire(RedisConstant.USER_TOKE_PREFIX+token, RedisConstant.USER_TOKEN_TTL, TimeUnit.MINUTES);
        return token;

    }
}
